﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WcfGeebaServer.ContentManage;
using WcfGeebaServer.Users;
using System.Data;

namespace WcfGeebaServer.DBDAL
{
    public class SubForumDA
    {
        public static SubForumDA GetSubForumDA()
        {
            return new SubForumDA();
        }

        /// <summary>
        /// Add sub forum 
        /// </summary>
        /// <param name="sf">the sub forum to add</param>
        /// <returns>True if succeeds, else false</returns>
        public bool AddSubForum(GSubForum sf) {
            bool res = false;

            if (Data.subForums.FindBysubForumTopic(sf.Topic) == null)
            {
                if (Data.subForumsAdapter.Insert(sf.Topic) == 0)
                {
                    return false;
                }
                Data.subForums.AddSubForumsRow(sf.Topic);
                Data.subForums.AcceptChanges();
                res = true;
            }
            return res;
        }

        /// <summary>
        /// Remove sub forum
        /// </summary>
        /// <param name="topic">The topic of the sub forum to remove</param>
        /// <returns>True if succeeds, else false</returns>
        public bool RemoveSubForum(GSubForum subforum) {

            GeebaDS.SubForumsRow toRemove = Data.subForums.FindBysubForumTopic(subforum.Topic);
            if (toRemove != null)
            {
                if (Data.subForumsAdapter.Delete(subforum.Topic) == 0)
                {
                    return false;
                }
                toRemove.Delete();
                Data.subForums.AcceptChanges();
                return true;
            }
            return false;
        }

        /// <summary>
        /// Get sub forum
        /// </summary>
        /// <param name="topic">The topic of the sub forum to find</param>
        /// <returns>GSubForum with the given topic, null if not found</returns>
        public GSubForum GetSubForum(string topic) {

            GeebaDS.SubForumsRow subforum = Data.subForums.FindBysubForumTopic(topic);
            if (subforum == null)
                return null;

            GSubForum res = new GSubForum(subforum.subForumTopic);
            return res;
        }
        
        /// <summary>
        /// Get all sub forums
        /// </summary>
        /// <returns>A list of all sub forums</returns>
        public List<GSubForum> GetSubForums() {
            List<GeebaDS.SubForumsRow> list =  Data.subForums.ToList();
            List<GSubForum> subforums = new List<GSubForum>();
            if (list.Count == 0)
                return subforums;

            foreach (GeebaDS.SubForumsRow row in list)
            {
                subforums.Add(new GSubForum(row.subForumTopic));
            }
            return subforums;
        }

        /// <summary>
        /// Get the threads of the subforum
        /// </summary>
        /// <param name="subforum">The subforum to get its threads</param>
        /// <returns>A list of threads of the subforum</returns>
        public List<GThread> GetThreads(GSubForum subforum)
        {
            List<GThread> subforumThreads;

            EnumerableRowCollection<GeebaDS.ThreadsRow> list = 
                       from row in Data.threads
                       where row.subForumTopic == subforum.Topic
                       && row.IsparentThreadNull()
                       select row;

            subforumThreads = new List<GThread>();
            Member m;
            foreach (GeebaDS.ThreadsRow row in list)
            {
                m = MemberDA.getMemberDA().GetMember(row.publishedBy);
                subforumThreads.Add(new GThread(row.thread_id, row.thread_subject, row.thread_content, m,
                    row.publishDate, row.modifiedDate));
            }
            return subforumThreads;
        }

        /// <summary>
        /// Get the number of the messages in subforum
        /// </summary>
        /// <param name="subforum">The subforum to get its messages number</param>
        /// <returns>The number of messages in subforum</returns>
        public int getMessagesCount(GSubForum subforum)
        {
            int res = -1;
            res = (from data in Data.threads
                        where data.subForumTopic == subforum.Topic
                        select data).Count();
            return res;
        }

        /// <summary>
        /// Get the last message posted by member in subforum.
        /// </summary>
        /// <param name="subforum">The subforum th search in the message.</param>
        /// <param name="member">The member that published the message to search.</param>
        /// <returns>The last message posted by member in subforum.</returns>
        public GThread GetLastMessage(GSubForum subforum, Member member)
        {
            GThread res = null;

            OrderedEnumerableRowCollection<GeebaDS.ThreadsRow> list = 
                       from row in Data.threads
                       where (row.publishedBy == member.Username &&
                       row.subForumTopic == subforum.Topic)
                       orderby row.publishDate
                       descending
                       select row;

            if (list.Count() > 0)
            {
                Member m = MemberDA.getMemberDA().GetMember(list.ElementAt(0).publishedBy);
                res = new GThread(list.ElementAt(0).thread_id, list.ElementAt(0).thread_subject, 
                    list.ElementAt(0).thread_content, m,
                    list.ElementAt(0).publishDate, list.ElementAt(0).modifiedDate);
            }

            return res;
        }

        /// <summary>
        /// Get the moderators of the given subforum.
        /// </summary>
        /// <param name="subforum">The subforum to find his moderators</param>
        /// <returns>A list of Member,ModeratorInfo of the subforum </returns>
        public List<KeyValuePair<Member,ModeratorInfo>> GetModerators(GSubForum subforum)
        {
            List<KeyValuePair<Member, ModeratorInfo>> result = new List<KeyValuePair<Member, ModeratorInfo>>();

            var moderators =
                       from moderatorInfo in Data.moderators
                       join member in Data.members on moderatorInfo.username equals member.username
                       where moderatorInfo.subForumTopic == subforum.Topic
                       select new { member, moderatorInfo };

            KeyValuePair<Member, ModeratorInfo> pair;
            foreach (var item in moderators)
            {
                pair = new KeyValuePair<Member, ModeratorInfo>(
                    new Member(item.member.username,item.member.password,item.member.isActive),
                    new ModeratorInfo(item.moderatorInfo.since));
                result.Add(pair);
            }
            return result;
        }

        /// <summary>
        /// Add new moderator with info to subforum.
        /// </summary>
        /// <param name="subforum">The subforum to add to.</param>
        /// <param name="moderator">The moderator to add.</param>
        /// <param name="info">The info of the moderator</param>
        /// <returns>True if succeed, else false.</returns>
        public bool AddModerator(GSubForum subforum, Member moderator, ModeratorInfo info)
        {
            if (Data.subForums.FindBysubForumTopic(subforum.Topic) == null)
                return false;
            if (Data.moderators.FindByusernamesubForumTopic(moderator.Username, subforum.Topic) != null)
                return false;
            if (Data.members.FindByusername(moderator.Username) == null)
                return false;
            if (Data.moderatorsAdapter.Insert(moderator.Username, subforum.Topic, DateTime.Now) == 0)
            {
                return false;
            }
            Data.moderators.AddModeratorInfoRow(moderator.Username, subforum.Topic, DateTime.Now);
            Data.moderators.AcceptChanges();
            if (moderator.UserType == UserType.Member && 
                Data.usersAdapter.SetUserType(UserType.Moderator.ToString(), moderator.Username, moderator.Username) == 0)
            {
                return false;
            }
            Data.members = Data.usersAdapter.GetMembers();
            moderator.UserType = UserType.Moderator;
            return true;
        }

        /// <summary>
        /// Remove moderator from subforum.
        /// </summary>
        /// <param name="subforum">The subforum to find in the moderator.</param>
        /// <param name="moderator">The moderator to remove.</param>
        /// <returns>True if succeed, else false.</returns>
        public bool RemoveModerator(GSubForum subforum, Member moderator)
        {
            if (Data.subForums.FindBysubForumTopic(subforum.Topic) == null)
                return false;
            
            GeebaDS.ModeratorInfoRow row = Data.moderators.FindByusernamesubForumTopic(moderator.Username, subforum.Topic);
            if (row == null)
                return false;

            if (Data.moderatorsAdapter.Delete(moderator.Username, subforum.Topic) == 0)
            {
                return false;
            }
            Data.moderators.RemoveModeratorInfoRow(row);
            Data.moderators.AcceptChanges();

            var count = (from mod in Data.moderators
                        where mod.username == moderator.Username
                        select mod).Count();
            if (count == 0 && moderator.UserType!= UserType.Admin)
            {
                if (Data.usersAdapter.SetUserType(UserType.Member.ToString(), moderator.Username, moderator.Username) == 0)
                {
                    return false;
                }
                Data.members = Data.usersAdapter.GetMembers();
                moderator.UserType = UserType.Member;
            }
            return true;
        }

        public int GetMessageCountByMember(Member member, GSubForum subForum)
        {
            int res = (from row in Data.threads
                         where row.publishedBy == member.Username &&
                         row.subForumTopic == subForum.Topic
                         select row).Count();
            return res;
        }

        public bool RemoveModerators(string subForumTopic)
        {
            var query = from mod in Data.moderators
                        join member in Data.members on mod.username equals member.username
                        where mod.subForumTopic == subForumTopic
                        select member;

            foreach (var mem in query)
            {
                if(mem.userType != UserType.Admin.ToString())
                    mem.userType = UserType.Member.ToString();
            }
            Data.members.AcceptChanges();
            //Data.members = Data.usersAdapter.GetMembers();



            if (Data.moderatorsAdapter.DeleteModeratorsBySubForum(subForumTopic) == 0)
            {
                return false;
            }

            Data.moderators = Data.moderatorsAdapter.GetData();

            return true;
        }

        public List<Member> getMembersPosted(GSubForum subForum)
        {
            List<Member> result = new List<Member>();

            var query = from thread in Data.threads
                        join member in Data.members on thread.publishedBy equals member.username
                        where thread.subForumTopic == subForum.Topic
                        select member.username;

            foreach (var postedMember in query)
            {
                result.Add(MemberDA.getMemberDA().GetMember(postedMember));
            }

            return result;

        }
    }
}